<?php
declare (strict_types=1);

namespace addons\Concurrency\driver\channels;

class Redis
{

    public $redis;

    public $prefix;

    public function set($key, $value, $time = 0)
    {
        $key = $this->prefix . $key;
        if (is_array($value)) {
            $value = json_encode($value);
        }
        if (!$time) {
            return $this->redis->set($key, $value);
        }
        return $this->redis->setex($key, $time, $value);
    }

    public function get($key)
    {
        return $this->redis->get($this->prefix . $key);
    }

    public function delete($key)
    {
        return $this->redis->del($this->prefix . $key);
    }

    public function incr($key, $value)
    {
        return $this->redis->incr($this->prefix . $key, $value);
    }

    public function decr($key, $value)
    {
        return $this->redis->decr($this->prefix . $key, $value);
    }

    public function eval($key, $num)
    {
        $lua = <<<LUA
                local value = redis.call('get', KEYS[1])
                if redis.call('exists', KEYS[1]) == 1 then
                    if value and tonumber(value) > 0 then
                        if redis.call('decr', KEYS[1]) > -1 then
                            return redis.call('get', KEYS[1])
                        else
                            return -1
                        end
                    else
                        return -1
                    end
                else
                    return 0
                end
                LUA;

        return $this->redis->eval($lua, [$this->prefix . $key], $num);
    }


    public function getRedis($config): object
    {
        $redisConfig = config('concurrency.redis');

        $this->redis = new \Redis();
        $result = $this->redis->connect($redisConfig['host'], $redisConfig['port']);
        if ($result === false) {
            throw new \Exception('redis connect error');
        }
        if ($redisConfig['password']) {
            $this->redis->auth($redisConfig['password']);
        }
        $this->prefix = !empty($config['prefix']) ? $config['prefix'] . ':' : '';

        return $this;
    }

    public static function make($config)
    {
        return \think\Container::getInstance()
            ->make(static::class)
            ->getRedis($config);
    }

}